#pragma once

#include <cstring>
#include <cerrno>
#include <signal.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

class nocopy // 不可拷贝的类
{
public:
    nocopy() = default;
    nocopy(const nocopy &) = delete;
    nocopy &operator=(const nocopy &) = delete;
};

enum Errno
{
    Err_Permiss = 1,
    Err_Use,
    Err_Socket,
    Err_Bind,
    Err_Listen,
    Err_Accept,
    Err_Connect,
    Err_Fork,
};

int Daemon(int nochdir, int noclose) // 守护进程化
{
    // 屏蔽会使进程异常的信号
    if (signal(SIGCHLD, SIG_IGN) == SIG_ERR)
        return -1;
    if (signal(SIGPIPE, SIG_IGN) == SIG_ERR)
        return -1;

    // 保证执行流不是进程组组长
    if (fork() > 0)
        exit(0);

    // 新启会话
    if (setsid() == -1)
        return -1;

    // 改变当前进程的工作目录
    if (!nochdir)
    {
        if (chdir("/") == -1)
            return -1;
    }

    // 关闭当前进程所关联的终端
    if (!noclose)
    {
        int fd = open("/dev/null", O_RDONLY | O_WRONLY);
        if (fd == -1)
            return -1;
        dup2(fd, 0);
        dup2(fd, 1);
        dup2(fd, 2);
        close(fd);
    }

    // 设置成功
    return 0;
}
